package com.ruoyi.web.controller.fdhController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.Utils.SmsUtils;
import com.ruoyi.web.entity.dto.SendSmsDto;
import com.ruoyi.web.entity.vo.LoginVo;
import com.ruoyi.web.fdhService.SysCaptchaService;
import com.ruoyi.web.fdhService.SysRoleService;
import com.ruoyi.web.fdhService.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author FDH
 * @Date 2021/5/28 17:57
 **/
@Api(tags = "用户登录相关")
@RestController
@CrossOrigin
@RequestMapping("/sys/user")
@Slf4j
public class LoginController {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysCaptchaService sysCaptchaService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysLoginService loginService;

    @ApiOperation("获取验证码")
    @GetMapping(value = "captcha.jpg", produces = MediaType.IMAGE_JPEG_VALUE)
    public void captcha(HttpServletResponse response, String uuid) throws IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        //获取图片验证码
        BufferedImage image = sysCaptchaService.getCaptcha(uuid);

        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }




/**
 * 分界线
 */


//    /**
//     * 手机号码/登录名+账号密码+图片验证码
//     */
//    @ApiOperation("手机号码/登录名+账号密码+图片验证码")
//    @PostMapping("/loginWithPassword")
//    AjaxResult loginWithPassword(@RequestBody LoginVo loginVo, HttpServletRequest request) {
//        // TODO: 2021/5/11 未做校验
//        try {
//
//            //检查验证码
//            boolean captcha = sysCaptchaService.validate(loginVo.getCaptcha());
//            if (!captcha) {
//
//                return AjaxResult.error("图片验证码不正确");
//            }
//            stringRedisTemplate.delete(loginVo.getUuid());
//            if (StringUtils.isNumeric(loginVo.getLoginNameOrMobile())) {
//                //手机登录
//                SysUser one = sysUserMapper.getUserByMobile(loginVo.getLoginNameOrMobile());
//                System.out.println("one:" + one);
//                if (one != null) {
//                    AjaxResult ajax = AjaxResult.success();
//                    // 生成令牌
//                    String token = loginService.login(one.getUserName(),loginVo.getPassword());
//                    ajax.put(Constants.TOKEN, token);
//                    return ajax;
//                }
//            }
//            //用户名登录
//            SysUser one = sysUserMapper.getUserByUserName(loginVo.getUserName());
//                    System.out.println("one2:" + one);
//            if (one != null) {
//                System.out.println("user_name:"+one.getUserName());
//                AjaxResult ajax = AjaxResult.success();
//                // 生成令牌
//                String token = loginService.login(one.getUserName(),loginVo.getPassword());
//                ajax.put(Constants.TOKEN, token);
//
//                return ajax;
//
//            } else {
//                System.out.println("++++");
//                return AjaxResult.error("账号或密码错误，登录失败。");
//            }
//
//        } catch (Exception e) {
//            return AjaxResult.error("异常:null pointer表示缺少必要字段, 异常信息:" + e.getMessage());
//        }
//
//    }

//    /**
//     * 手机号码+短信验证码登录
//     *
//     * @return
//     */
//    @ApiOperation("手机号码+短信验证码登录")
//    @PostMapping("/loginWithSms")
//    AjaxResult loginWithSms(@RequestBody LoginVo loginVo, HttpServletRequest request) {
//        try {
//
//            if (loginVo.getSmsCode() != null && loginVo.getSmsCode().equals(stringRedisTemplate.opsForValue().get(loginVo.getLoginNameOrMobile() + "_login"))) {
//                stringRedisTemplate.delete(loginVo.getLoginNameOrMobile() + "_login");
//                final SysUser one = sysUserMapper.getUserByMobile(loginVo.getLoginNameOrMobile());
//                if (one != null) {
//
//                    AjaxResult ajax = AjaxResult.success();
//                    // 生成令牌
//                    String token = loginService.login(one.getUserName(), one.getPassword());
//                    ajax.put(Constants.TOKEN, token);
//                    return ajax;
//                } else {
//                    return AjaxResult.success("手机号错误，登录失败。");
//                }
//                // return RStatic.error("该用户未注册");
//            }
//            return AjaxResult.error("手机验证码错误");
//        } catch (Exception e) {
//            return AjaxResult.error("登录异常：" + e.getMessage());
//        }
//    }

    /**
     * 修改密码
     *
     * @param loginVo
     * @param request
     * @return
     */
    @ApiOperation("用手机验证码修改密码")
    @PostMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody LoginVo loginVo, HttpServletRequest request) {
        if (loginVo.getSmsCode() != null && loginVo.getSmsCode().equals(stringRedisTemplate.opsForValue().get(loginVo.getLoginNameOrMobile() + "_resetPwd"))) {
            stringRedisTemplate.delete(loginVo.getLoginNameOrMobile() + "_resetPwd");

            final SysUser one = sysUserMapper.getUserByMobile(loginVo.getLoginNameOrMobile());
            if (one != null) {

                one.setPassword(loginVo.getPassword());
                int i = sysUserMapper.updateUser(one);
                if (i>0) {
                    return AjaxResult.success("修改成功");
                }else {
                    return AjaxResult.error("修改失败");
                }
            } else {
                return AjaxResult.error("手机号错误");
            }
        } else {
            return AjaxResult.error("验证码错误");
        }
    }

    @ApiOperation("验证手机号是否存在")
    @PostMapping("/isMobile")
    AjaxResult isMobile(String mobile){
        SysUser user = sysUserMapper.getUserByMobile(mobile);
        if (user != null) {
           return AjaxResult.error("手机号已存在");
        }else {
           return AjaxResult.success("可创建");
        }
    }
    @ApiOperation("验证账户是否存在")
    @PostMapping("/isUserName")
    AjaxResult isUserName(String userName){
        SysUser user = sysUserMapper.getUserByUserName(userName);
        if (user != null) {
            return AjaxResult.error("账户已存在");
        }else {
            return AjaxResult.success("可创建");
        }
    }
    @ApiOperation("验证昵称是否存在")
    @PostMapping("/isNickName")
    AjaxResult isNickName(String nickName){
        SysUser user = sysUserMapper.getUserByNickName(nickName);
        if (user != null) {
            return AjaxResult.error("昵称已存在");
        }else {
            return AjaxResult.success("可创建");
        }
    }

    /**
     * 手机号+账号密码+短信验证码+图片验证码注册
     */
    @ApiOperation("手机号+账号密码+短信验证码+图片验证码注册")
    @PostMapping("/registerWithSms")
    AjaxResult registerWithSms(@RequestBody LoginVo loginVo) {
        try {
            if (loginVo.getSmsCode() != null && loginVo.getSmsCode().equals(stringRedisTemplate.opsForValue().get(loginVo.getLoginNameOrMobile() + "_register"))) {
                stringRedisTemplate.delete(loginVo.getLoginNameOrMobile() + "_register");
                final SysUser sysUserEntity = new SysUser();
                sysUserEntity.setPhonenumber(loginVo.getLoginNameOrMobile());
                sysUserEntity.setPassword(SecurityUtils.encryptPassword(loginVo.getPassword()));
                sysUserEntity.setUserName(loginVo.getUserName());
                sysUserEntity.setNickName(loginVo.getNickName());

                int i = sysUserMapper.insertUser(sysUserEntity);
                if (i>0) {
                    SysRole role = sysRoleMapper.getSysRoleByRoleName("普通角色");
                    if (role != null) {
                        SysUserRole userRole = new SysUserRole();
                        userRole.setRoleId(role.getRoleId());
                        userRole.setUserId(sysUserEntity.getUserId());
                    } else {
                        return AjaxResult.error("绑定普通角色失败");
                    }

                    return AjaxResult.success("注册成功");
                } else {
                    return AjaxResult.error("注册失败");
                }
            } else {
                return AjaxResult.error("验证码失效");
            }
        } catch (DuplicateKeyException de) {
            return AjaxResult.error("该用户已注册");
        } catch (Exception e) {
            return AjaxResult.error("未知异常:" + e.getMessage());
        }
    }


    @ApiOperation("全局短信验证码发送")
    @PostMapping("/sendSms")
    public AjaxResult sendSms(@RequestBody @NotNull @NotEmpty @Valid SendSmsDto sse) {

        //检查验证码
        boolean captcha = sysCaptchaService.validate(sse.getVerifyCodeId());
        if (!captcha) {

            return AjaxResult.error("图片验证码不正确");
        } else {
            stringRedisTemplate.delete(sse.getVerifyCodeId());
        }

        if (!"login".equals(sse.getType()) && !"register".equals(sse.getType()) && !"resetPwd".equals(sse.getType())) {
            return AjaxResult.error("无效短信类型");
        }
        //发送短信类型为login时，检查该用户是否已经注册
        new QueryWrapper<>().eq("mobile", sse.getMobile());
        if (("login".equals(sse.getType()) || "resetPwd".equals(sse.getType())) && sysUserMapper.getUserByMobile(sse.getMobile()) == null) {
            //当用户不存在时发送login类型短信会被拒绝
            return AjaxResult.error("该手机用户尚未注册");
        }
        String sixRandom = SmsUtils.getSixRandom();
        if (SmsUtils.sendMessage(sse.getMobile(), sixRandom)) {
            log.info("发送验证码{}成功，存入缓存5分钟", sixRandom);
            String phoneNumber = sse.getMobile();
            //检查缓存
            String loginStr = stringRedisTemplate.opsForValue().get(phoneNumber + "_" + sse.getType());
            if (null == loginStr) {
                //失效时间 5 分钟
                stringRedisTemplate.opsForValue().set(phoneNumber + "_" + sse.getType(), sixRandom, 5, TimeUnit.MINUTES);
            } else {
                Long expireMinutes = stringRedisTemplate.getExpire(phoneNumber + "_" + sse.getType(), TimeUnit.MINUTES);
                return AjaxResult.error("已发送，请" + expireMinutes + "分钟后再试");
            }
        } else {
            return AjaxResult.error("操作失败");
        }
        return AjaxResult.success("操作成功");
    }

    @ApiOperation("退出登录")
    @PostMapping("/logout")
    public AjaxResult logout(long userId) {

        Boolean isDelToken = stringRedisTemplate.delete(String.valueOf(userId));
        if (isDelToken) {
            return AjaxResult.success("退出成功，token已删除");
        } else {
            return AjaxResult.error("退出失败");
        }
    }

}
